// /// Copy from TabBar
// ///
//
// import 'dart:math' as math;
// import 'dart:ui' show lerpDouble;
//
// import 'package:flutter/foundation.dart';
// import 'package:flutter/gestures.dart' show DragStartBehavior;
// import 'package:flutter/material.dart';
// import 'package:flutter/rendering.dart';
// import 'package:flutter/widgets.dart';
// import 'package:flutter_syt/utils/click_utils.dart';
//
// const double _kTabHeight = 46.0;
// const double _kTextAndIconTabHeight = 72.0;
//
// class XxOoTab extends StatelessWidget implements PreferredSizeWidget {
//   const XxOoTab({
//     Key? key,
//     this.text,
//     this.icon,
//     this.iconMargin = const EdgeInsets.only(bottom: 10.0),
//     this.height,
//     this.child,
//   })  : assert(text != null || child != null || icon != null),
//         assert(text == null || child == null),
//         super(key: key);
//
//   final String? text;
//
//   final Widget? child;
//
//   final Widget? icon;
//
//   final EdgeInsetsGeometry iconMargin;
//
//   final double? height;
//
//   Widget _buildLabelText() {
//     return child ?? Text(text!, softWrap: false, overflow: TextOverflow.fade);
//   }
//
//   @override
//   Widget build(BuildContext context) {
//     assert(debugCheckHasMaterial(context));
//
//     final double calculatedHeight;
//     final Widget label;
//     if (icon == null) {
//       calculatedHeight = _kTabHeight;
//       label = _buildLabelText();
//     } else if (text == null && child == null) {
//       calculatedHeight = _kTabHeight;
//       label = icon!;
//     } else {
//       calculatedHeight = _kTextAndIconTabHeight;
//       label = Column(
//         mainAxisAlignment: MainAxisAlignment.center,
//         crossAxisAlignment: CrossAxisAlignment.center,
//         children: <Widget>[
//           Container(
//             margin: iconMargin,
//             child: icon,
//           ),
//           _buildLabelText(),
//         ],
//       );
//     }
//
//     return SizedBox(
//       height: height ?? calculatedHeight,
//       child: Center(
//         widthFactor: 1.0,
//         child: label,
//       ),
//     );
//   }
//
//   @override
//   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
//     super.debugFillProperties(properties);
//     properties.add(StringProperty('text', text, defaultValue: null));
//     properties
//         .add(DiagnosticsProperty<Widget>('icon', icon, defaultValue: null));
//   }
//
//   @override
//   Size get preferredSize {
//     debugPrint("--------------------> 1");
//     if (height != null)
//       return Size.fromHeight(height!);
//     else if ((text != null || child != null) && icon != null)
//       return const Size.fromHeight(_kTextAndIconTabHeight);
//     else
//       return const Size.fromHeight(_kTabHeight);
//   }
// }
//
// class _XxOoTabStyle extends AnimatedWidget {
//   const _XxOoTabStyle({
//     Key? key,
//     required Animation<double> animation,
//     required this.selected,
//     required this.labelColor,
//     required this.unselectedLabelColor,
//     required this.labelStyle,
//     required this.unselectedLabelStyle,
//     required this.child,
//   }) : super(key: key, listenable: animation);
//
//   final TextStyle? labelStyle;
//   final TextStyle? unselectedLabelStyle;
//   final bool selected;
//   final Color? labelColor;
//   final Color? unselectedLabelColor;
//   final Widget child;
//
//   @override
//   Widget build(BuildContext context) {
//     final ThemeData themeData = Theme.of(context);
//     final TabBarTheme tabBarTheme = TabBarTheme.of(context);
//     final Animation<double> animation = listenable as Animation<double>;
//
//     final TextStyle defaultStyle = (labelStyle ??
//             tabBarTheme.labelStyle ??
//             themeData.primaryTextTheme.bodyMedium!)
//         .copyWith(inherit: true);
//     final TextStyle defaultUnselectedStyle = (unselectedLabelStyle ??
//             tabBarTheme.unselectedLabelStyle ??
//             labelStyle ??
//             themeData.primaryTextTheme.bodyMedium!
//             )
//         .copyWith(inherit: true);
//     final TextStyle textStyle = selected
//         ? TextStyle.lerp(defaultStyle, defaultUnselectedStyle, animation.value)!
//         : TextStyle.lerp(
//             defaultUnselectedStyle, defaultStyle, animation.value)!;
//
//     final Color selectedColor = labelColor ??
//         tabBarTheme.labelColor ??
//         themeData.primaryTextTheme.bodyMedium!.color!;
//     final Color unselectedColor = unselectedLabelColor ??
//         tabBarTheme.unselectedLabelColor ??
//         selectedColor.withAlpha(0xB2); // 70% alpha
//     final Color color = selected
//         ? Color.lerp(selectedColor, unselectedColor, animation.value)!
//         : Color.lerp(unselectedColor, selectedColor, animation.value)!;
//
//     return DefaultTextStyle(
//       style: textStyle.copyWith(color: color),
//       child: IconTheme.merge(
//         data: IconThemeData(
//           size: 24.0,
//           color: color,
//         ),
//         child: child,
//       ),
//     );
//   }
// }
//
// typedef _XxOoLayoutCallback = void Function(
//     List<double> xOffsets, TextDirection textDirection, double width);
//
// class _XxOoTabLabelBarRenderer extends RenderFlex {
//   _XxOoTabLabelBarRenderer({
//     List<RenderBox>? children,
//     required Axis direction,
//     required MainAxisSize mainAxisSize,
//     required MainAxisAlignment mainAxisAlignment,
//     required CrossAxisAlignment crossAxisAlignment,
//     required TextDirection textDirection,
//     required VerticalDirection verticalDirection,
//     required this.onPerformLayout,
//   })  : assert(onPerformLayout != null),
//         assert(textDirection != null),
//         super(
//           children: children,
//           direction: direction,
//           mainAxisSize: mainAxisSize,
//           mainAxisAlignment: mainAxisAlignment,
//           crossAxisAlignment: crossAxisAlignment,
//           textDirection: textDirection,
//           verticalDirection: verticalDirection,
//         );
//
//   _XxOoLayoutCallback onPerformLayout;
//
//   @override
//   void performLayout() {
//     super.performLayout();
//     RenderBox? child = firstChild;
//     final List<double> xOffsets = <double>[];
//     while (child != null) {
//       final FlexParentData childParentData =
//           child.parentData! as FlexParentData;
//       xOffsets.add(childParentData.offset.dx);
//       assert(child.parentData == childParentData);
//       child = childParentData.nextSibling;
//     }
//     assert(textDirection != null);
//     switch (textDirection!) {
//       case TextDirection.rtl:
//         xOffsets.insert(0, size.width);
//         break;
//       case TextDirection.ltr:
//         xOffsets.add(size.width);
//         break;
//     }
//     onPerformLayout(xOffsets, textDirection!, size.width);
//   }
// }
//
// class _XxOoTabLabelBar extends Flex {
//   _XxOoTabLabelBar({
//     Key? key,
//     List<Widget> children = const <Widget>[],
//     required this.onPerformLayout,
//   }) : super(
//           key: key,
//           children: children,
//           direction: Axis.horizontal,
//           mainAxisSize: MainAxisSize.max,
//           mainAxisAlignment: MainAxisAlignment.start,
//           crossAxisAlignment: CrossAxisAlignment.center,
//           verticalDirection: VerticalDirection.down,
//         );
//
//   final _XxOoLayoutCallback onPerformLayout;
//
//   @override
//   RenderFlex createRenderObject(BuildContext context) {
//     return _XxOoTabLabelBarRenderer(
//       direction: direction,
//       mainAxisAlignment: mainAxisAlignment,
//       mainAxisSize: mainAxisSize,
//       crossAxisAlignment: crossAxisAlignment,
//       textDirection: getEffectiveTextDirection(context)!,
//       verticalDirection: verticalDirection,
//       onPerformLayout: onPerformLayout,
//     );
//   }
//
//   @override
//   void updateRenderObject(
//       BuildContext context, _XxOoTabLabelBarRenderer renderObject) {
//     super.updateRenderObject(context, renderObject);
//     renderObject.onPerformLayout = onPerformLayout;
//   }
// }
//
// double _indexChangeProgress(TabController controller) {
//   final double controllerValue = controller.animation!.value;
//   final double previousIndex = controller.previousIndex.toDouble();
//   final double currentIndex = controller.index.toDouble();
//
//   if (!controller.indexIsChanging)
//     return (currentIndex - controllerValue).abs().clamp(0.0, 1.0);
//
//   return (controllerValue - currentIndex).abs() /
//       (currentIndex - previousIndex).abs();
// }
//
// class _IndicatorPainter extends CustomPainter {
//   _IndicatorPainter({
//     required this.controller,
//     required this.indicator,
//     required this.indicatorSize,
//     required this.tabKeys,
//     required _IndicatorPainter? old,
//     required this.indicatorPadding,
//   })  : assert(controller != null),
//         assert(indicator != null),
//         super(repaint: controller.animation) {
//     if (old != null)
//       saveTabOffsets(old._currentTabOffsets, old._currentTextDirection);
//   }
//
//   final TabController controller;
//   final Decoration indicator;
//   final TabBarIndicatorSize? indicatorSize;
//   final EdgeInsetsGeometry indicatorPadding;
//   final List<GlobalKey> tabKeys;
//
//   List<double>? _currentTabOffsets;
//   TextDirection? _currentTextDirection;
//
//   Rect? _currentRect;
//   BoxPainter? _painter;
//   bool _needsPaint = false;
//
//   void markNeedsPaint() {
//     _needsPaint = true;
//   }
//
//   void dispose() {
//     _painter?.dispose();
//   }
//
//   void saveTabOffsets(List<double>? tabOffsets, TextDirection? textDirection) {
//     _currentTabOffsets = tabOffsets;
//     _currentTextDirection = textDirection;
//   }
//
//   int get maxTabIndex => _currentTabOffsets!.length - 2;
//
//   double centerOf(int tabIndex) {
//     assert(_currentTabOffsets != null);
//     assert(_currentTabOffsets!.isNotEmpty);
//     assert(tabIndex >= 0);
//     assert(tabIndex <= maxTabIndex);
//     return (_currentTabOffsets![tabIndex] + _currentTabOffsets![tabIndex + 1]) /
//         2.0;
//   }
//
//   Rect indicatorRect(Size tabBarSize, int tabIndex) {
//     assert(_currentTabOffsets != null);
//     assert(_currentTextDirection != null);
//     assert(_currentTabOffsets!.isNotEmpty);
//     assert(tabIndex >= 0);
//     assert(tabIndex <= maxTabIndex);
//     double tabLeft, tabRight;
//     switch (_currentTextDirection!) {
//       case TextDirection.rtl:
//         tabLeft = _currentTabOffsets![tabIndex + 1];
//         tabRight = _currentTabOffsets![tabIndex];
//         break;
//       case TextDirection.ltr:
//         tabLeft = _currentTabOffsets![tabIndex];
//         tabRight = _currentTabOffsets![tabIndex + 1];
//         break;
//     }
//
//     if (indicatorSize == TabBarIndicatorSize.label) {
//       final double tabWidth = tabKeys[tabIndex].currentContext!.size!.width;
//       final double delta = ((tabRight - tabLeft) - tabWidth) / 2.0;
//       tabLeft += delta;
//       tabRight -= delta;
//     }
//
//     final EdgeInsets insets = indicatorPadding.resolve(_currentTextDirection);
//     final Rect rect =
//         Rect.fromLTWH(tabLeft, 0.0, tabRight - tabLeft, tabBarSize.height);
//
//     if (!(rect.size >= insets.collapsedSize)) {
//       throw FlutterError(
//         'indicatorPadding insets should be less than Tab Size\n'
//         'Rect Size : ${rect.size}, Insets: ${insets.toString()}',
//       );
//     }
//     return insets.deflateRect(rect);
//   }
//
//   @override
//   void paint(Canvas canvas, Size size) {
//     _needsPaint = false;
//     _painter ??= indicator.createBoxPainter(markNeedsPaint);
//
//     final double index = controller.index.toDouble();
//     final double value = controller.animation!.value;
//     final bool ltr = index > value;
//     final int from = (ltr ? value.floor() : value.ceil()).clamp(0, maxTabIndex);
//     final int to = (ltr ? from + 1 : from - 1).clamp(0, maxTabIndex);
//     final Rect fromRect = indicatorRect(size, from);
//     final Rect toRect = indicatorRect(size, to);
//     _currentRect = Rect.lerp(fromRect, toRect, (value - from).abs());
//     assert(_currentRect != null);
//
//     final ImageConfiguration configuration = ImageConfiguration(
//       size: _currentRect!.size,
//       textDirection: _currentTextDirection,
//     );
//     _painter!.paint(canvas, _currentRect!.topLeft, configuration);
//   }
//
//   @override
//   bool shouldRepaint(_IndicatorPainter old) {
//     return _needsPaint ||
//         controller != old.controller ||
//         indicator != old.indicator ||
//         tabKeys.length != old.tabKeys.length ||
//         (!listEquals(_currentTabOffsets, old._currentTabOffsets)) ||
//         _currentTextDirection != old._currentTextDirection;
//   }
// }
//
// class _ChangeAnimation extends Animation<double>
//     with AnimationWithParentMixin<double> {
//   _ChangeAnimation(this.controller);
//
//   final TabController controller;
//
//   @override
//   Animation<double> get parent => controller.animation!;
//
//   @override
//   void removeStatusListener(AnimationStatusListener listener) {
//     if (controller.animation != null) super.removeStatusListener(listener);
//   }
//
//   @override
//   void removeListener(VoidCallback listener) {
//     if (controller.animation != null) super.removeListener(listener);
//   }
//
//   @override
//   double get value => _indexChangeProgress(controller);
// }
//
// class _DragAnimation extends Animation<double>
//     with AnimationWithParentMixin<double> {
//   _DragAnimation(this.controller, this.index);
//
//   final TabController controller;
//   final int index;
//
//   @override
//   Animation<double> get parent => controller.animation!;
//
//   @override
//   void removeStatusListener(AnimationStatusListener listener) {
//     if (controller.animation != null) super.removeStatusListener(listener);
//   }
//
//   @override
//   void removeListener(VoidCallback listener) {
//     if (controller.animation != null) super.removeListener(listener);
//   }
//
//   @override
//   double get value {
//     assert(!controller.indexIsChanging);
//     final double controllerMaxValue = (controller.length - 1).toDouble();
//     final double controllerValue =
//         controller.animation!.value.clamp(0.0, controllerMaxValue);
//     return (controllerValue - index.toDouble()).abs().clamp(0.0, 1.0);
//   }
// }
//
// class _XxOoTabBarScrollPosition extends ScrollPositionWithSingleContext {
//   _XxOoTabBarScrollPosition({
//     required ScrollPhysics physics,
//     required ScrollContext context,
//     required ScrollPosition? oldPosition,
//     required this.tabBar,
//   }) : super(
//           physics: physics,
//           context: context,
//           initialPixels: null,
//           oldPosition: oldPosition,
//         );
//
//   final _XxOoTabBarState tabBar;
//
//   bool? _initialViewportDimensionWasZero;
//
//   @override
//   bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) {
//     bool result = true;
//     if (_initialViewportDimensionWasZero != true) {
//       assert(viewportDimension != null);
//       _initialViewportDimensionWasZero = viewportDimension != 0.0;
//       correctPixels(tabBar._initialScrollOffset(
//           viewportDimension, minScrollExtent, maxScrollExtent));
//       result = false;
//     }
//     return super.applyContentDimensions(minScrollExtent, maxScrollExtent) &&
//         result;
//   }
// }
//
// class _XxOoTabBarScrollController extends ScrollController {
//   _XxOoTabBarScrollController(this.tabBar);
//
//   final _XxOoTabBarState tabBar;
//
//   @override
//   ScrollPosition createScrollPosition(ScrollPhysics physics,
//       ScrollContext context, ScrollPosition? oldPosition) {
//     return _XxOoTabBarScrollPosition(
//       physics: physics,
//       context: context,
//       oldPosition: oldPosition,
//       tabBar: tabBar,
//     );
//   }
// }
//
// class XxOoTabBar extends StatefulWidget implements PreferredSizeWidget {
//   const XxOoTabBar({
//     Key? key,
//     required this.tabs,
//     this.controller,
//     this.isScrollable = false,
//     this.padding,
//     this.indicatorColor,
//     this.automaticIndicatorColorAdjustment = true,
//     this.indicatorWeight = 2.0,
//     this.indicatorPadding = EdgeInsets.zero,
//     this.indicator,
//     this.indicatorSize,
//     this.labelColor,
//     this.labelStyle,
//     this.labelPadding,
//     this.unselectedLabelColor,
//     this.unselectedLabelStyle,
//     this.dragStartBehavior = DragStartBehavior.start,
//     this.overlayColor,
//     this.mouseCursor,
//     this.enableFeedback,
//     this.onTap,
//     this.physics,
//   })  : assert(tabs != null),
//         assert(isScrollable != null),
//         assert(dragStartBehavior != null),
//         assert(indicator != null ||
//             (indicatorWeight != null && indicatorWeight > 0.0)),
//         assert(indicator != null || (indicatorPadding != null)),
//         super(key: key);
//
//   final List<Widget> tabs;
//
//   final TabController? controller;
//
//   final bool isScrollable;
//
//   final EdgeInsetsGeometry? padding;
//
//   final Color? indicatorColor;
//
//   final double indicatorWeight;
//
//   final EdgeInsetsGeometry indicatorPadding;
//
//   final Decoration? indicator;
//
//   final bool automaticIndicatorColorAdjustment;
//
//   final TabBarIndicatorSize? indicatorSize;
//
//   final Color? labelColor;
//
//   final Color? unselectedLabelColor;
//
//   final TextStyle? labelStyle;
//
//   final EdgeInsetsGeometry? labelPadding;
//
//   final TextStyle? unselectedLabelStyle;
//
//   final MaterialStateProperty<Color?>? overlayColor;
//
//   final DragStartBehavior dragStartBehavior;
//
//   final MouseCursor? mouseCursor;
//
//   final bool? enableFeedback;
//
//   final ValueChanged<int>? onTap;
//
//   final ScrollPhysics? physics;
//
//   @override
//   Size get preferredSize {
//     double maxHeight = _kTabHeight;
//     for (final Widget item in tabs) {
//       if (item is PreferredSizeWidget) {
//         final double itemHeight = item.preferredSize.height;
//         maxHeight = math.max(itemHeight, maxHeight);
//       }
//     }
//     debugPrint(
//         "Size -----------> ${Size.fromHeight(maxHeight + indicatorWeight)}");
//     return Size.fromHeight(maxHeight + indicatorWeight);
//   }
//
//   bool get tabHasTextAndIcon {
//     for (final Widget item in tabs) {
//       if (item is PreferredSizeWidget) {
//         if (item.preferredSize.height == _kTextAndIconTabHeight) return true;
//       }
//     }
//     return false;
//   }
//
//   @override
//   State<XxOoTabBar> createState() => _XxOoTabBarState();
// }
//
// class _XxOoTabBarState extends State<XxOoTabBar> {
//   ScrollController? _scrollController;
//   TabController? _controller;
//   _IndicatorPainter? _indicatorPainter;
//   int? _currentIndex;
//   late double _tabStripWidth;
//   late List<GlobalKey> _tabKeys;
//
//   @override
//   void initState() {
//     super.initState();
//     _tabKeys = widget.tabs.map((Widget tab) => GlobalKey()).toList();
//   }
//
//   Decoration get _indicator {
//     if (widget.indicator != null) return widget.indicator!;
//     final TabBarTheme tabBarTheme = TabBarTheme.of(context);
//     if (tabBarTheme.indicator != null) return tabBarTheme.indicator!;
//
//     Color color = widget.indicatorColor ?? Theme.of(context).indicatorColor;
//     if (widget.automaticIndicatorColorAdjustment &&
//         color.value == Material.of(context)?.color?.value) color = Colors.white;
//
//     return UnderlineTabIndicator(
//       borderSide: BorderSide(
//         width: widget.indicatorWeight,
//         color: color,
//       ),
//     );
//   }
//
//   bool get _controllerIsValid => _controller?.animation != null;
//
//   void _updateTabController() {
//     final TabController? newController =
//         widget.controller ?? DefaultTabController.of(context);
//     assert(() {
//       if (newController == null) {
//         throw FlutterError(
//           'No TabController for ${widget.runtimeType}.\n'
//           'When creating a ${widget.runtimeType}, you must either provide an explicit '
//           'TabController using the "controller" property, or you must ensure that there '
//           'is a DefaultTabController above the ${widget.runtimeType}.\n'
//           'In this case, there was neither an explicit controller nor a default controller.',
//         );
//       }
//       return true;
//     }());
//
//     if (newController == _controller) return;
//
//     if (_controllerIsValid) {
//       _controller!.animation!.removeListener(_handleTabControllerAnimationTick);
//       _controller!.removeListener(_handleTabControllerTick);
//     }
//     _controller = newController;
//     if (_controller != null) {
//       _controller!.animation!.addListener(_handleTabControllerAnimationTick);
//       _controller!.addListener(_handleTabControllerTick);
//       _currentIndex = _controller!.index;
//     }
//   }
//
//   void _initIndicatorPainter() {
//     _indicatorPainter = !_controllerIsValid
//         ? null
//         : _IndicatorPainter(
//             controller: _controller!,
//             indicator: _indicator,
//             indicatorSize:
//                 widget.indicatorSize ?? TabBarTheme.of(context).indicatorSize,
//             indicatorPadding: widget.indicatorPadding,
//             tabKeys: _tabKeys,
//             old: _indicatorPainter,
//           );
//   }
//
//   @override
//   void didChangeDependencies() {
//     super.didChangeDependencies();
//     assert(debugCheckHasMaterial(context));
//     _updateTabController();
//     _initIndicatorPainter();
//   }
//
//   @override
//   void didUpdateWidget(XxOoTabBar oldWidget) {
//     super.didUpdateWidget(oldWidget);
//     if (widget.controller != oldWidget.controller) {
//       _updateTabController();
//       _initIndicatorPainter();
//     } else if (widget.indicatorColor != oldWidget.indicatorColor ||
//         widget.indicatorWeight != oldWidget.indicatorWeight ||
//         widget.indicatorSize != oldWidget.indicatorSize ||
//         widget.indicator != oldWidget.indicator) {
//       _initIndicatorPainter();
//     }
//
//     if (widget.tabs.length > oldWidget.tabs.length) {
//       final int delta = widget.tabs.length - oldWidget.tabs.length;
//       _tabKeys.addAll(List<GlobalKey>.generate(delta, (int n) => GlobalKey()));
//     } else if (widget.tabs.length < oldWidget.tabs.length) {
//       _tabKeys.removeRange(widget.tabs.length, oldWidget.tabs.length);
//     }
//   }
//
//   @override
//   void dispose() {
//     _indicatorPainter!.dispose();
//     if (_controllerIsValid) {
//       _controller!.animation!.removeListener(_handleTabControllerAnimationTick);
//       _controller!.removeListener(_handleTabControllerTick);
//     }
//     _controller = null;
//     // We don't own the _controller Animation, so it's not disposed here.
//     super.dispose();
//   }
//
//   int get maxTabIndex => _indicatorPainter!.maxTabIndex;
//
//   double _tabScrollOffset(
//       int index, double viewportWidth, double minExtent, double maxExtent) {
//     if (!widget.isScrollable) return 0.0;
//     double tabCenter = _indicatorPainter!.centerOf(index);
//     switch (Directionality.of(context)) {
//       case TextDirection.rtl:
//         tabCenter = _tabStripWidth - tabCenter;
//         break;
//       case TextDirection.ltr:
//         break;
//     }
//     return (tabCenter - viewportWidth / 2.0).clamp(minExtent, maxExtent);
//   }
//
//   double _tabCenteredScrollOffset(int index) {
//     final ScrollPosition position = _scrollController!.position;
//     return _tabScrollOffset(index, position.viewportDimension,
//         position.minScrollExtent, position.maxScrollExtent);
//   }
//
//   double _initialScrollOffset(
//       double viewportWidth, double minExtent, double maxExtent) {
//     return _tabScrollOffset(
//         _currentIndex!, viewportWidth, minExtent, maxExtent);
//   }
//
//   void _scrollToCurrentIndex() {
//     final double offset = _tabCenteredScrollOffset(_currentIndex!);
//     _scrollController!
//         .animateTo(offset, duration: kTabScrollDuration, curve: Curves.ease);
//   }
//
//   void _scrollToControllerValue() {
//     final double? leadingPosition = _currentIndex! > 0
//         ? _tabCenteredScrollOffset(_currentIndex! - 1)
//         : null;
//     final double middlePosition = _tabCenteredScrollOffset(_currentIndex!);
//     final double? trailingPosition = _currentIndex! < maxTabIndex
//         ? _tabCenteredScrollOffset(_currentIndex! + 1)
//         : null;
//
//     final double index = _controller!.index.toDouble();
//     final double value = _controller!.animation!.value;
//     final double offset;
//     if (value == index - 1.0)
//       offset = leadingPosition ?? middlePosition;
//     else if (value == index + 1.0)
//       offset = trailingPosition ?? middlePosition;
//     else if (value == index)
//       offset = middlePosition;
//     else if (value < index)
//       offset = leadingPosition == null
//           ? middlePosition
//           : lerpDouble(middlePosition, leadingPosition, index - value)!;
//     else
//       offset = trailingPosition == null
//           ? middlePosition
//           : lerpDouble(middlePosition, trailingPosition, value - index)!;
//
//     _scrollController!.jumpTo(offset);
//   }
//
//   void _handleTabControllerAnimationTick() {
//     assert(mounted);
//     if (!_controller!.indexIsChanging && widget.isScrollable) {
//       // Sync the TabBar's scroll position with the TabBarView's PageView.
//       _currentIndex = _controller!.index;
//       _scrollToControllerValue();
//     }
//   }
//
//   void _handleTabControllerTick() {
//     if (_controller!.index != _currentIndex) {
//       _currentIndex = _controller!.index;
//       if (widget.isScrollable) _scrollToCurrentIndex();
//     }
//     setState(() {});
//   }
//
//   void _saveTabOffsets(
//       List<double> tabOffsets, TextDirection textDirection, double width) {
//     _tabStripWidth = width;
//     _indicatorPainter?.saveTabOffsets(tabOffsets, textDirection);
//   }
//
//   void _handleTap(int index) {
//     assert(index >= 0 && index < widget.tabs.length);
//     _controller!.animateTo(index);
//     widget.onTap?.call(index);
//   }
//
//   Widget _buildStyledTab(
//       Widget child, bool selected, Animation<double> animation) {
//     return _XxOoTabStyle(
//       animation: animation,
//       selected: selected,
//       labelColor: widget.labelColor,
//       unselectedLabelColor: widget.unselectedLabelColor,
//       labelStyle: widget.labelStyle,
//       unselectedLabelStyle: widget.unselectedLabelStyle,
//       child: child,
//     );
//   }
//
//   @override
//   Widget build(BuildContext context) {
//     assert(debugCheckHasMaterialLocalizations(context));
//     assert(() {
//       if (_controller!.length != widget.tabs.length) {
//         throw FlutterError(
//           "Controller's length property (${_controller!.length}) does not match the "
//           "number of tabs (${widget.tabs.length}) present in TabBar's tabs property.",
//         );
//       }
//       return true;
//     }());
//     final MaterialLocalizations localizations =
//         MaterialLocalizations.of(context);
//     if (_controller!.length == 0) {
//       return Container(
//         height: _kTabHeight + widget.indicatorWeight,
//       );
//     }
//
//     final TabBarTheme tabBarTheme = TabBarTheme.of(context) as TabBarTheme;
//
//     final List<Widget> wrappedTabs =
//         List<Widget>.generate(widget.tabs.length, (int index) {
//       const double verticalAdjustment =
//           (_kTextAndIconTabHeight - _kTabHeight) / 2.0;
//       EdgeInsetsGeometry? adjustedPadding;
//
//       if (widget.tabs[index] is PreferredSizeWidget) {
//         final PreferredSizeWidget tab =
//             widget.tabs[index] as PreferredSizeWidget;
//         if (widget.tabHasTextAndIcon &&
//             tab.preferredSize.height == _kTabHeight) {
//           if (widget.labelPadding != null || tabBarTheme.labelPadding != null) {
//             adjustedPadding = (widget.labelPadding ?? tabBarTheme.labelPadding!)
//                 .add(const EdgeInsets.symmetric(vertical: verticalAdjustment));
//           } else {
//             adjustedPadding = const EdgeInsets.symmetric(
//                 vertical: verticalAdjustment, horizontal: 16.0);
//           }
//         }
//       }
//
//       return Center(
//         heightFactor: 1.0,
//         child: Padding(
//           padding: adjustedPadding ??
//               widget.labelPadding ??
//               tabBarTheme.labelPadding ??
//               kTabLabelPadding,
//           child: KeyedSubtree(
//             key: _tabKeys[index],
//             child: widget.tabs[index],
//           ),
//         ),
//       );
//     });
//
//     if (_controller != null) {
//       final int previousIndex = _controller!.previousIndex;
//
//       if (_controller!.indexIsChanging) {
//         // The user tapped on a tab, the tab controller's animation is running.
//         assert(_currentIndex != previousIndex);
//         final Animation<double> animation = _ChangeAnimation(_controller!);
//         wrappedTabs[_currentIndex!] =
//             _buildStyledTab(wrappedTabs[_currentIndex!], true, animation);
//         wrappedTabs[previousIndex] =
//             _buildStyledTab(wrappedTabs[previousIndex], false, animation);
//       } else {
//         // The user is dragging the TabBarView's PageView left or right.
//         final int tabIndex = _currentIndex!;
//         final Animation<double> centerAnimation =
//             _DragAnimation(_controller!, tabIndex);
//         wrappedTabs[tabIndex] =
//             _buildStyledTab(wrappedTabs[tabIndex], true, centerAnimation);
//         if (_currentIndex! > 0) {
//           final int tabIndex = _currentIndex! - 1;
//           final Animation<double> previousAnimation =
//               ReverseAnimation(_DragAnimation(_controller!, tabIndex));
//           wrappedTabs[tabIndex] =
//               _buildStyledTab(wrappedTabs[tabIndex], false, previousAnimation);
//         }
//         if (_currentIndex! < widget.tabs.length - 1) {
//           final int tabIndex = _currentIndex! + 1;
//           final Animation<double> nextAnimation =
//               ReverseAnimation(_DragAnimation(_controller!, tabIndex));
//           wrappedTabs[tabIndex] =
//               _buildStyledTab(wrappedTabs[tabIndex], false, nextAnimation);
//         }
//       }
//     }
//
//     final int tabCount = widget.tabs.length;
//     for (int index = 0; index < tabCount; index += 1) {
//       wrappedTabs[index] = InkWell(
//         mouseCursor: widget.mouseCursor ?? SystemMouseCursors.click,
//         onTap: ClickUtils.debounce(() {
//           _handleTap(index);
//         }),
//         enableFeedback: widget.enableFeedback ?? true,
//         overlayColor: widget.overlayColor,
//         child: Padding(
//           padding: EdgeInsets.only(bottom: widget.indicatorWeight),
//           child: Stack(
//             children: <Widget>[
//               wrappedTabs[index],
//               Semantics(
//                 selected: index == _currentIndex,
//                 label: localizations.tabLabel(
//                     tabIndex: index + 1, tabCount: tabCount),
//               ),
//             ],
//           ),
//         ),
//       );
//       if (!widget.isScrollable)
//         wrappedTabs[index] = Expanded(child: wrappedTabs[index]);
//     }
//
//     Widget tabBar = CustomPaint(
//       painter: _indicatorPainter,
//       child: _XxOoTabStyle(
//         animation: kAlwaysDismissedAnimation,
//         selected: false,
//         labelColor: widget.labelColor,
//         unselectedLabelColor: widget.unselectedLabelColor,
//         labelStyle: widget.labelStyle,
//         unselectedLabelStyle: widget.unselectedLabelStyle,
//         child: _XxOoTabLabelBar(
//           onPerformLayout: _saveTabOffsets,
//           children: wrappedTabs,
//         ),
//       ),
//     );
//
//     if (widget.isScrollable) {
//       _scrollController ??= _XxOoTabBarScrollController(this);
//       tabBar = SingleChildScrollView(
//         dragStartBehavior: widget.dragStartBehavior,
//         scrollDirection: Axis.horizontal,
//         controller: _scrollController,
//         padding: widget.padding,
//         physics: widget.physics,
//         child: tabBar,
//       );
//     } else if (widget.padding != null) {
//       tabBar = Padding(
//         padding: widget.padding!,
//         child: tabBar,
//       );
//     }
//
//     return tabBar;
//   }
// }
//
// class XxOoTabBarView extends StatefulWidget {
//   const XxOoTabBarView({
//     Key? key,
//     required this.children,
//     this.controller,
//     this.physics,
//     this.dragStartBehavior = DragStartBehavior.start,
//   })  : assert(children != null),
//         assert(dragStartBehavior != null),
//         super(key: key);
//   final TabController? controller;
//   final List<Widget> children;
//
//   final ScrollPhysics? physics;
//
//   final DragStartBehavior dragStartBehavior;
//
//   @override
//   State<XxOoTabBarView> createState() => _XxOoTabBarViewState();
// }
//
// class _XxOoTabBarViewState extends State<XxOoTabBarView> {
//   TabController? _controller;
//   late PageController _pageController;
//   late List<Widget> _children;
//   late List<Widget> _childrenWithKey;
//   int? _currentIndex;
//   int _warpUnderwayCount = 0;
//
//   bool get _controllerIsValid => _controller?.animation != null;
//
//   void _updateTabController() {
//     final TabController? newController =
//         widget.controller ?? DefaultTabController.of(context);
//     assert(() {
//       if (newController == null) {
//         throw FlutterError(
//           'No TabController for ${widget.runtimeType}.\n'
//           'When creating a ${widget.runtimeType}, you must either provide an explicit '
//           'TabController using the "controller" property, or you must ensure that there '
//           'is a DefaultTabController above the ${widget.runtimeType}.\n'
//           'In this case, there was neither an explicit controller nor a default controller.',
//         );
//       }
//       return true;
//     }());
//
//     if (newController == _controller) return;
//
//     if (_controllerIsValid)
//       _controller!.animation!.removeListener(_handleTabControllerAnimationTick);
//     _controller = newController;
//     if (_controller != null)
//       _controller!.animation!.addListener(_handleTabControllerAnimationTick);
//   }
//
//   @override
//   void initState() {
//     super.initState();
//     _updateChildren();
//   }
//
//   @override
//   void didChangeDependencies() {
//     super.didChangeDependencies();
//     _updateTabController();
//     _currentIndex = _controller?.index;
//     _pageController = PageController(initialPage: _currentIndex ?? 0);
//   }
//
//   @override
//   void didUpdateWidget(XxOoTabBarView oldWidget) {
//     super.didUpdateWidget(oldWidget);
//     if (widget.controller != oldWidget.controller) _updateTabController();
//     if (widget.children != oldWidget.children && _warpUnderwayCount == 0)
//       _updateChildren();
//   }
//
//   @override
//   void dispose() {
//     if (_controllerIsValid)
//       _controller!.animation!.removeListener(_handleTabControllerAnimationTick);
//     _controller = null;
//     // We don't own the _controller Animation, so it's not disposed here.
//     super.dispose();
//   }
//
//   void _updateChildren() {
//     _children = widget.children;
//     _childrenWithKey = KeyedSubtree.ensureUniqueKeysForList(widget.children);
//   }
//
//   void _handleTabControllerAnimationTick() {
//     if (_warpUnderwayCount > 0 || !_controller!.indexIsChanging)
//       return; // This widget is driving the controller's animation.
//
//     if (_controller!.index != _currentIndex) {
//       _currentIndex = _controller!.index;
//       _warpToCurrentIndex();
//     }
//   }
//
//   Future<void> _warpToCurrentIndex() async {
//     if (!mounted) return Future<void>.value();
//
//     if (_pageController.page == _currentIndex!.toDouble())
//       return Future<void>.value();
//
//     final int previousIndex = _controller!.previousIndex;
//     if ((_currentIndex! - previousIndex).abs() == 1) {
//       _warpUnderwayCount += 1;
//       await _pageController.animateToPage(_currentIndex!,
//           duration: kTabScrollDuration, curve: Curves.ease);
//       _warpUnderwayCount -= 1;
//       return Future<void>.value();
//     }
//
//     assert((_currentIndex! - previousIndex).abs() > 1);
//     final int initialPage = _currentIndex! > previousIndex
//         ? _currentIndex! - 1
//         : _currentIndex! + 1;
//     final List<Widget> originalChildren = _childrenWithKey;
//     setState(() {
//       _warpUnderwayCount += 1;
//
//       _childrenWithKey = List<Widget>.from(_childrenWithKey, growable: false);
//       final Widget temp = _childrenWithKey[initialPage];
//       _childrenWithKey[initialPage] = _childrenWithKey[previousIndex];
//       _childrenWithKey[previousIndex] = temp;
//     });
//     _pageController.jumpToPage(initialPage);
//
//     await _pageController.animateToPage(_currentIndex!,
//         duration: kTabScrollDuration, curve: Curves.ease);
//     if (!mounted) return Future<void>.value();
//     setState(() {
//       _warpUnderwayCount -= 1;
//       if (widget.children != _children) {
//         _updateChildren();
//       } else {
//         _childrenWithKey = originalChildren;
//       }
//     });
//   }
//
//   bool _handleScrollNotification(ScrollNotification notification) {
//     if (_warpUnderwayCount > 0) return false;
//
//     if (notification.depth != 0) return false;
//
//     _warpUnderwayCount += 1;
//     if (notification is ScrollUpdateNotification &&
//         !_controller!.indexIsChanging) {
//       if ((_pageController.page! - _controller!.index).abs() > 1.0) {
//         _controller!.index = _pageController.page!.floor();
//         _currentIndex = _controller!.index;
//       }
//       _controller!.offset =
//           (_pageController.page! - _controller!.index).clamp(-1.0, 1.0);
//     } else if (notification is ScrollEndNotification) {
//       _controller!.index = _pageController.page!.round();
//       _currentIndex = _controller!.index;
//       if (!_controller!.indexIsChanging)
//         _controller!.offset =
//             (_pageController.page! - _controller!.index).clamp(-1.0, 1.0);
//     }
//     _warpUnderwayCount -= 1;
//
//     return false;
//   }
//
//   @override
//   Widget build(BuildContext context) {
//     assert(() {
//       if (_controller!.length != widget.children.length) {
//         throw FlutterError(
//           "Controller's length property (${_controller!.length}) does not match the "
//           "number of tabs (${widget.children.length}) present in TabBar's tabs property.",
//         );
//       }
//       return true;
//     }());
//     return NotificationListener<ScrollNotification>(
//       onNotification: _handleScrollNotification,
//       child: PageView(
//         dragStartBehavior: widget.dragStartBehavior,
//         controller: _pageController,
//         physics: widget.physics == null
//             ? const PageScrollPhysics().applyTo(const ClampingScrollPhysics())
//             : const PageScrollPhysics().applyTo(widget.physics),
//         children: _childrenWithKey,
//       ),
//     );
//   }
// }
//
// class XxOoTabPageSelectorIndicator extends StatelessWidget {
//   const XxOoTabPageSelectorIndicator({
//     Key? key,
//     required this.backgroundColor,
//     required this.borderColor,
//     required this.size,
//   })  : assert(backgroundColor != null),
//         assert(borderColor != null),
//         assert(size != null),
//         super(key: key);
//
//   final Color backgroundColor;
//
//   final Color borderColor;
//
//   final double size;
//
//   @override
//   Widget build(BuildContext context) {
//     return Container(
//       width: size,
//       height: size,
//       margin: const EdgeInsets.all(4.0),
//       decoration: BoxDecoration(
//         color: backgroundColor,
//         border: Border.all(color: borderColor),
//         shape: BoxShape.circle,
//       ),
//     );
//   }
// }
//
// class XxOoTabPageSelector extends StatelessWidget {
//   const XxOoTabPageSelector({
//     Key? key,
//     this.controller,
//     this.indicatorSize = 12.0,
//     this.color,
//     this.selectedColor,
//   })  : assert(indicatorSize != null && indicatorSize > 0.0),
//         super(key: key);
//
//   final TabController? controller;
//
//   final double indicatorSize;
//
//   final Color? color;
//
//   /// [ColorScheme.secondary].
//   final Color? selectedColor;
//
//   Widget _buildTabIndicator(
//     int tabIndex,
//     TabController tabController,
//     ColorTween selectedColorTween,
//     ColorTween previousColorTween,
//   ) {
//     final Color background;
//     if (tabController.indexIsChanging) {
//       // The selection's animation is animating from previousValue to value.
//       final double t = 1.0 - _indexChangeProgress(tabController);
//       if (tabController.index == tabIndex)
//         background = selectedColorTween.lerp(t)!;
//       else if (tabController.previousIndex == tabIndex)
//         background = previousColorTween.lerp(t)!;
//       else
//         background = selectedColorTween.begin!;
//     } else {
//       // The selection's offset reflects how far the TabBarView has / been dragged
//       // to the previous page (-1.0 to 0.0) or the next page (0.0 to 1.0).
//       final double offset = tabController.offset;
//       if (tabController.index == tabIndex) {
//         background = selectedColorTween.lerp(1.0 - offset.abs())!;
//       } else if (tabController.index == tabIndex - 1 && offset > 0.0) {
//         background = selectedColorTween.lerp(offset)!;
//       } else if (tabController.index == tabIndex + 1 && offset < 0.0) {
//         background = selectedColorTween.lerp(-offset)!;
//       } else {
//         background = selectedColorTween.begin!;
//       }
//     }
//     return XxOoTabPageSelectorIndicator(
//       backgroundColor: background,
//       borderColor: selectedColorTween.end!,
//       size: indicatorSize,
//     );
//   }
//
//   @override
//   Widget build(BuildContext context) {
//     final Color fixColor = color ?? Colors.transparent;
//     final Color fixSelectedColor =
//         selectedColor ?? Theme.of(context).colorScheme.secondary;
//     final ColorTween selectedColorTween =
//         ColorTween(begin: fixColor, end: fixSelectedColor);
//     final ColorTween previousColorTween =
//         ColorTween(begin: fixSelectedColor, end: fixColor);
//     final TabController? tabController =
//         controller ?? DefaultTabController.of(context);
//     assert(() {
//       if (tabController == null) {
//         throw FlutterError(
//           'No TabController for $runtimeType.\n'
//           'When creating a $runtimeType, you must either provide an explicit TabController '
//           'using the "controller" property, or you must ensure that there is a '
//           'DefaultTabController above the $runtimeType.\n'
//           'In this case, there was neither an explicit controller nor a default controller.',
//         );
//       }
//       return true;
//     }());
//     final Animation<double> animation = CurvedAnimation(
//       parent: tabController!.animation!,
//       curve: Curves.fastOutSlowIn,
//     );
//     return AnimatedBuilder(
//       animation: animation,
//       builder: (BuildContext context, Widget? child) {
//         return Semantics(
//           label: 'Page ${tabController.index + 1} of ${tabController.length}',
//           child: Row(
//             mainAxisSize: MainAxisSize.min,
//             children:
//                 List<Widget>.generate(tabController.length, (int tabIndex) {
//               return _buildTabIndicator(tabIndex, tabController,
//                   selectedColorTween, previousColorTween);
//             }).toList(),
//           ),
//         );
//       },
//     );
//   }
// }
